#include "wen_frustum.h"

using namespace wen;

Frustum::Frustum()
{
	m_pFrustum = new D3DXPLANE[6];
}

Frustum::~Frustum()
{
}

void Frustum::CreateFrustum(float screenDepth, D3DXMATRIX projectionMatrix, D3DXMATRIX viewMatrix)
{	

	/*float zMinimum, r;
        
        // Calculate the minimum Z distance in the frustum.
        zMinimum = -projectionMatrix._43 / projectionMatrix._33;
        r = screenDepth / (screenDepth - zMinimum);
        projectionMatrix._33 = r;
        projectionMatrix._43 = -r * zMinimum;

    D3DXMATRIX matrix;

	//Create the frustum matrix from the view matrix and updated projection matrix.
    D3DXMatrixMultiply(&matrix, &viewMatrix, &projectionMatrix);	

    // Calculate near plane of frustum.
    m_planes[0].a = matrix._14 + matrix._13;
    m_planes[0].b = matrix._24 + matrix._23;
    m_planes[0].c = matrix._34 + matrix._33;
    m_planes[0].d = matrix._44 + matrix._43;
    D3DXPlaneNormalize(&m_planes[0], &m_planes[0]);

    // Calculate far plane of frustum.
    m_planes[1].a = matrix._14 - matrix._13; 
    m_planes[1].b = matrix._24 - matrix._23;
    m_planes[1].c = matrix._34 - matrix._33;
    m_planes[1].d = matrix._44 - matrix._43;
    D3DXPlaneNormalize(&m_planes[1], &m_planes[1]);

    // Calculate left plane of frustum.
    m_planes[2].a = matrix._14 + matrix._11; 
    m_planes[2].b = matrix._24 + matrix._21;
    m_planes[2].c = matrix._34 + matrix._31;
    m_planes[2].d = matrix._44 + matrix._41;
    D3DXPlaneNormalize(&m_planes[2], &m_planes[2]);

    // Calculate right plane of frustum.
    m_planes[3].a = matrix._14 - matrix._11; 
    m_planes[3].b = matrix._24 - matrix._21;
    m_planes[3].c = matrix._34 - matrix._31;
    m_planes[3].d = matrix._44 - matrix._41;
    D3DXPlaneNormalize(&m_planes[3], &m_planes[3]);

    // Calculate top plane of frustum.
    m_planes[4].a = matrix._14 - matrix._12; 
    m_planes[4].b = matrix._24 - matrix._22;
    m_planes[4].c = matrix._34 - matrix._32;
    m_planes[4].d = matrix._44 - matrix._42;
    D3DXPlaneNormalize(&m_planes[4], &m_planes[4]);

    // Calculate bottom plane of frustum.
    m_planes[5].a = matrix._14 + matrix._12;
    m_planes[5].b = matrix._24 + matrix._22;
    m_planes[5].c = matrix._34 + matrix._32;
    m_planes[5].d = matrix._44 + matrix._42;
    D3DXPlaneNormalize(&m_planes[5], &m_planes[5]);*/

		//matview = view matrix
//	vEyePt	- position where viewer stands (camera)
//	vLookatPt - position to look at
//	vUpVec - vector (0,-1,0) for orientation
//D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );

//matProj = projection matrix
//	fovy - D3DX_PI/4
//	aspectxy - screenx / screeny
//	zmin - 1.0f
//	zmax - 100.0f
//D3DXMatrixPerspectiveFovLH(&matProj, fovy, aspectxy, zmin, zmax);


	//	
	D3DXMATRIX viewProjection;
	D3DXMatrixMultiply( &viewProjection, &viewMatrix, &projectionMatrix );

	// Left plane
	m_pFrustum[0].a = viewProjection._14 + viewProjection._11;
	m_pFrustum[0].b = viewProjection._24 + viewProjection._21;
	m_pFrustum[0].c = viewProjection._34 + viewProjection._31;
	m_pFrustum[0].d = viewProjection._44 + viewProjection._41;

	// Right plane
	m_pFrustum[1].a = viewProjection._14 - viewProjection._11;
	m_pFrustum[1].b = viewProjection._24 - viewProjection._21;
	m_pFrustum[1].c = viewProjection._34 - viewProjection._31;
	m_pFrustum[1].d = viewProjection._44 - viewProjection._41;

	// Top plane
	m_pFrustum[2].a = viewProjection._14 - viewProjection._12;
	m_pFrustum[2].b = viewProjection._24 - viewProjection._22;
	m_pFrustum[2].c = viewProjection._34 - viewProjection._32;
	m_pFrustum[2].d = viewProjection._44 - viewProjection._42;

	// Bottom plane
	m_pFrustum[3].a = viewProjection._14 + viewProjection._12;
	m_pFrustum[3].b = viewProjection._24 + viewProjection._22;
	m_pFrustum[3].c = viewProjection._34 + viewProjection._32;
	m_pFrustum[3].d = viewProjection._44 + viewProjection._42;

	// Near plane
	m_pFrustum[4].a = viewProjection._13;
	m_pFrustum[4].b = viewProjection._23;
	m_pFrustum[4].c = viewProjection._33;
	m_pFrustum[4].d = viewProjection._43;

	// Far plane
	m_pFrustum[5].a = viewProjection._14 - viewProjection._13;
	m_pFrustum[5].b = viewProjection._24 - viewProjection._23;
	m_pFrustum[5].c = viewProjection._34 - viewProjection._33;
	m_pFrustum[5].d = viewProjection._44 - viewProjection._43; 

	// Normalize planes
	for(int i=0;i<6;i++)
	{	
		D3DXPlaneNormalize(&m_pFrustum[i], &m_pFrustum[i]);
	}
}

bool Frustum::CheckIfPointIsInsideFrustum(float x, float y, float z)
{
	//Check if the point is inside all six planes of the view frustum.
    for(int i = 0; i < 6; i++)
	{
		//if(D3DXPlaneDotCoord(&m_planes[i], &D3DXVECTOR3(x, y, z)) < 0.0f)
		if(D3DXPlaneDotCoord(&m_pFrustum[i], &D3DXVECTOR3(x, y, z)) < 0.0f)
		{
			return false;
		}
	}

	return true;

		/*for(int i=0;i<6;i++)
		{	
			float f = D3DXPlaneDotCoord(&m_pFrustum[i], &vec);
			if(f < 0 )
			{	
			return FALSE;
			}
			} 
		return true;*/
}

bool Frustum::CheckIfPointIsInsideFrustum(D3DXVECTOR3 vect)
{
	return CheckIfPointIsInsideFrustum(vect.x, vect.y, vect.z);
}